use std::collections::HashMap;
use std::io::{BufRead, BufReader, Read};
use std::net::TcpStream;
use crate::request::{method::Method, version::Version};

const HEADER_SPLITE_CHAR    : &str = ": ";
const HTTP_PROTOCAL         : &str = "HTTP";

const CONTENT_LENGHT_HEADER        : &str  = "Content-Length";

#[derive(Debug)]
pub(crate) struct HttpRequest {
    pub method          :       Method,
    pub url             :       String,
    pub version         :       Version,
    pub header          :       HashMap<String,String>,
    pub body            :       String,
}

impl<'a> HttpRequest {
    pub fn parse_request(stream: &TcpStream) ->Self {

        let header = HashMap::new();
        let mut http_request = HttpRequest{
            method: Method::GET,
            url: "".to_string(),
            version: Version::V1_1,
            header,
            body: "".to_string(),
        };
        
        let mut reader = BufReader::new(stream);
        // Read first line
        let mut method_http_url = String::new();
        let _result = reader.by_ref().read_line(&mut method_http_url);
        //解析第一行，method， protocol， uri
        let (m,u,v) = parse_method(method_http_url);
        http_request.method = m;
        http_request.url = u;
        http_request.version = v;

        //解析header， header 都有一个“: ”

        for line_wrap in reader.by_ref().lines() {
            //如果是post 请求，header与 body 是使用/r/n 分割开的
           let line = match line_wrap {
                Ok(line)=> line,
               Err(_)=>String::new(),
            };
            if line.is_empty() {
                break;
            }
            let (k,v) = parse_header(line);
            http_request.header.insert(k,v);
        }
        if http_request.method == Method::GET {
             return http_request;
        }
        
        //http_request.header = header;
        //如果是post 请求，解析body
        let content_length_str= http_request.header.get(CONTENT_LENGHT_HEADER).unwrap();

        if !content_length_str.is_empty() {
            let content_length = content_length_str.parse::<usize>().unwrap();
            let mut body_bytes = vec![0; content_length];
            let result = reader.by_ref().read_exact(&mut body_bytes);
            let is_read_success = match result {
                Ok(_) => true,
                Err(e) => {
                    eprint!("{}", e.to_string());
                    false
                },
            };

            if is_read_success {
                http_request.body = String::from_utf8(body_bytes).unwrap();
            }
        }
        println!("after parse, the http request is {:?}", http_request);

        /*let mut is_body = false;
        for line in lines {
            if line.contains(HEADER_SPLITE_CHAR){
                let (k,v) = parse_header(line);
                http_request.header.insert(k,v);

            } else if line.contains(HTTP_PROTOCAL){
                let (m,u,v) = parse_method(line);
                http_request.method = m;
                http_request.url = u;
                http_request.version = v;
            } else if line.len()==0 {
                if !is_body{is_body = true}
            } else if is_body{
                http_request.body += &line;
            } else{
                panic!("xxxxxxxxxxxxx");
            }
        }*/
        http_request
    }

}

pub fn parse_header(line: String) ->(String,String){
    let  header_item = line.split_once(HEADER_SPLITE_CHAR);
    (header_item.unwrap().0.trim().to_string(), header_item.unwrap().1.trim().to_string())
}

fn parse_method(line: String)-> (Method,String,Version) {
    //第一行由method protocol 和 uri 路径组成，空格隔开
    /*if line.len() != 3 {
        panic!("the request format error");
    }*/
    let mut items   = line.split_whitespace();
    let method      = items.next().unwrap();
    let url         = items.next().unwrap();
    let version     = items.next().unwrap();
    (method.into(),url.to_string(),version.into())
}
